#include <afxwin.h>     // MFC core and standard components
#include <afxcmn.h>	
#include "resource.h"   // main symbols
#include <cmath>

//Globals
CEdit * pInputOutput;
CButton * pEquals;
CBrush CalculatorBrush;

double Number1;
double Number2;
double Result;
double Memory;
bool NextExpression;
bool NeedToClear;
bool ClickedEquals;
bool PasteMemory;
char oper;

CString TEMP;

class Calculator : public CDialog {
public:
    Calculator(CWnd* pParent = NULL): CDialog(Calculator::IDD, pParent) {    }

    // Dialog Data, name of dialog form
    enum{IDD = IDD_Interface};

    //--------------------------------------------------------

    //Called right after constructor. Initialize things here.
    virtual BOOL OnInitDialog() 
    { 
            CDialog::OnInitDialog();
	        pInputOutput = (CEdit *) GetDlgItem(IDC_InputOutput);
			pEquals = (CButton *) GetDlgItem(IDC_NumEquals);
	        //pInputOutput->SetFocus();
	        CalculatorBrush.CreateSolidBrush(RGB(255, 255, 255));
            Initialize();
            return true; 
    }

//--------------------------------------------------------

    //Message Handlers for Dialog class object
	afx_msg void key0() { KeyNumber("0"); }
	afx_msg void key1() { KeyNumber("1"); }
	afx_msg void key2() { KeyNumber("2"); }
	afx_msg void key3() { KeyNumber("3"); }
	afx_msg void key4() { KeyNumber("4"); }
	afx_msg void key5() { KeyNumber("5"); }
	afx_msg void key6() { KeyNumber("6"); }
	afx_msg void key7() { KeyNumber("7"); }
	afx_msg void key8() { KeyNumber("8"); }
	afx_msg void key9() { KeyNumber("9"); }

	afx_msg void keyPeriod() { KeyNumber("."); }
	afx_msg void keyEquals() { Equals(); }
	afx_msg void keyAdd() { Calculate('a'); }
	afx_msg void keySubtract() { Calculate('s'); }
	afx_msg void keyMultiply() { Calculate('m'); }
	afx_msg void keyDivide() { Calculate('d'); }
	afx_msg void keyPower() { Calculate('p'); }
	afx_msg void keyCube() { Cube(); }
	afx_msg void keySquare() { Square(); }
	afx_msg void keySquareRoot() { SquareRoot(); }
	afx_msg void keyMemory() { MemoryKey(); }
	afx_msg void EraseMemory() { MemoryClear(); }
	afx_msg void keyCE() { Erase(); }
	afx_msg void keyFarenheit() { CelciusToFarenheit(); }
	afx_msg void keyCelcius() { FarenheitToCelcius(); }
	afx_msg void keyMiles() { MilesToKilometers(); }
	afx_msg void keyKilometers() { KilometersToMiles(); }
	afx_msg void Quit() { EndDialog(IDOK); }
    //--------------------------------------------------------
	

	afx_msg void About() 
	{  
	        MessageBox(L"Calculator 3.0 - 2006 - C. Germany", L"Calculator 3.0 - HELP");
	}

    //--------------------------------------------------------

	afx_msg void Help() 
	{ 
             //Illustrates how to use multi-array and convert. Could just use CString.
	         char HELPTEXT[5][55] = { 
				 "This program is a fully functional calculator.\r\n",
			     "It was created as an MFC tutorial for students.\n",
				 "Its purpose is to display the logic processes\n",
				 "and progam flow between the user interface and \n",
				 "processing of input through the MFC CEdit control."
	             };

            char Message[280] = ""; 

	        for(int z = 0; z < 5; z++)
            { strncat_s(Message, HELPTEXT[z], 55); }

			CString TEMP = Message;

	        MessageBox(TEMP, L"Calculator 3.0 - HELP");
	}
	
    //--------------------------------------------------------

    //Calculator Functions

	void Initialize()
	{
         NextExpression = false;
	     NeedToClear = false;
	     ClickedEquals = false;
	     PasteMemory = false;
	     Number1 = 0.0; 
	     Number2 = 0.0; 
	     Result = 0.0;
	     Memory = 0.0;
	     oper = ' ';
	}
    //--------------------------------------------------------
    //In 2008 take in put as a CString and convert it to char array
	void KeyNumber(char digit[1])
	{
	     if(NeedToClear) 
		 { 
			 pInputOutput->SetWindowText(L""); 
			 NeedToClear = false; 
		 }

         pInputOutput->GetWindowText(TEMP);

		 char num[21] = "";
		 for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }

		 strncat_s(num,digit,20);

		 TEMP = num;
	     pInputOutput->SetWindowText(TEMP);  
	}
    //--------------------------------------------------------

    void Calculate(char op)
    {
         oper = op;

         pInputOutput->GetWindowText(TEMP);

		 char num[21] = "";
		 for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }

         if(NextExpression)
         {
	        if(!ClickedEquals)
	        {
                 Number2 = atof(num);

                 switch(oper)
                 {
                     case 'a' : Number1 = Number1 + Number2; break;
                     case 's' : Number1 = Number1 - Number2; break;
                     case 'm' : Number1 = Number1 * Number2; break;
					 case 'd' : if(Number2 == 0) { Number1 = 0; }
								else { Number1 = Number1 / Number2; } 
								break;
                     case 'p' : Number1 = pow(Number1,Number2); break;
                     default : break;
                 }
                  

                 char Answer[20];
			  

		         //itoa(Number1, Answer, 10); //Converts int, but truncates decimal
                 //Instead, use sprintf() to convert double or double to string
	             

				 sprintf_s(Answer,"%g",Number1);
				 TEMP = Answer;
                 pInputOutput->SetWindowText(TEMP);
		         NeedToClear = true;
	        }

	     else { ClickedEquals = false; }
       }

       else
       {
	       Number1 = atof(num);
	       NeedToClear = true;
	       NextExpression = true;
       }

    }//close Calculate()

    //--------------------------------------------------------

    void Equals() 
    { 
	     Calculate(oper);
	     NeedToClear = true;
	     ClickedEquals = true;
    }

    //--------------------------------------------------------

    void Erase()
    {  
	     pInputOutput->SetWindowText(L"");
         NextExpression = false;
	     NeedToClear = false;
	     ClickedEquals = false;
	     Number1 = 0.0; 
	     Number2 = 0.0; 
	     Result = 0.0;
	     oper = ' ';
    }

    //--------------------------------------------------------

    void Cube()
    {
         char num[20] = ""; 
	     double numtemp = 0.0;
	     pInputOutput->GetWindowText(TEMP);

         for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }

	     numtemp = atof(num);
         numtemp = numtemp * numtemp * numtemp;
	     sprintf_s(num,"%g",numtemp);
		 TEMP = num;
	     pInputOutput->SetWindowText(TEMP);
    }

    //--------------------------------------------------------

    void Square()
    {
         char num[20] = ""; 
	     double numtemp = 0.0;
	     pInputOutput->GetWindowText(TEMP);

         for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }

	     numtemp = atof(num);
         numtemp = numtemp * numtemp;
	     sprintf_s(num,"%g",numtemp);
		 TEMP = num;
	     pInputOutput->SetWindowText(TEMP);
    }

    //--------------------------------------------------------

    void SquareRoot()
    {
	     char num[20] = "";
	     pInputOutput->GetWindowText(TEMP);

		 for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }

	     Number1 = atof(num);
		 Number1 = sqrt(Number1);
         sprintf_s(num,"%g",Number1);

		 TEMP = num;
	     pInputOutput->SetWindowText(TEMP);
    }

    //--------------------------------------------------------

    void MemoryKey()
    {
         char num[20] = "";

         if(PasteMemory)
	     {
            sprintf_s(num,"%g",Memory);
			TEMP = num;
	        pInputOutput->SetWindowText(TEMP);
	     }

	     else
	     {
            pInputOutput->GetWindowText(TEMP);

            for(int x = 0; x < TEMP.GetLength(); x++) 
		    { num[x] = (char) TEMP[x]; }

            Memory = atof(num);
	        PasteMemory = true;
	     }
    }

    //--------------------------------------------------------

    void MemoryClear() 
	{ 
		 PasteMemory = false; 
		 Memory = 0.0; 
	}

    //--------------------------------------------------------

    void CelciusToFarenheit()
    {
         char num[20];    
         pInputOutput->GetWindowText(TEMP);

         for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }
	     

		 double Farenheit = atof(num);
	     Farenheit = (Farenheit * 9 / 5) + 32;
         sprintf_s(num,"%g",Farenheit); 

		 TEMP = num;
         pInputOutput->SetWindowText(TEMP);
    }

//-------------------------------------------------------------

    void FarenheitToCelcius()
    {
         char num[20];    
         pInputOutput->GetWindowText(TEMP);

         for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }

	     double Celcius = atof(num);
	     Celcius = ((Celcius - 32) * 5) / 9;
         sprintf_s(num,"%g",Celcius);   

		 TEMP = num;
         pInputOutput->SetWindowText(TEMP);
    }
//-------------------------------------------------------------

    void KilometersToMiles()
    { 
	     char num[20] = "";
	     pInputOutput->GetWindowText(TEMP);

         for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }

	     double x = atof(num);
	     x = x / 1.609347;
	     sprintf_s(num,"%g",x);

		 TEMP = num;
	     pInputOutput->SetWindowText(TEMP);
    }
//-------------------------------------------------------------

    void MilesToKilometers()
    { 
	     char num[20] = "";
	     pInputOutput->GetWindowText(TEMP);

         for(int x = 0; x < TEMP.GetLength(); x++) 
		 { num[x] = (char) TEMP[x]; }

		 double x = atof(num);
	     x = x * 1.609347; 
	     sprintf_s(num,"%g",x);

		 TEMP = num;
	     pInputOutput->SetWindowText(TEMP);
    }
//-------------------------------------------------------------

	DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(Calculator, CDialog)
      //Listen for and map COLOR events   
      ON_WM_CTLCOLOR() 
      ON_COMMAND(IDC_Num0, key0)
      ON_COMMAND(IDC_Num1, key1)
      ON_COMMAND(IDC_Num2, key2)
      ON_COMMAND(IDC_Num3, key3)
      ON_COMMAND(IDC_Num4, key4)
      ON_COMMAND(IDC_Num5, key5)
      ON_COMMAND(IDC_Num6, key6)
      ON_COMMAND(IDC_Num7, key7)
      ON_COMMAND(IDC_Num8, key8)
      ON_COMMAND(IDC_Num9, key9)
      ON_COMMAND(IDC_Num7, key7)
      ON_COMMAND(IDC_Num8, key8)
      ON_COMMAND(IDC_Num9, key9)
      ON_COMMAND(IDC_NumPeriod, keyPeriod)
      ON_COMMAND(IDC_NumEquals, keyEquals)
      ON_COMMAND(IDC_NumAdd, keyAdd)
      ON_COMMAND(IDC_NumSubtract, keySubtract)
      ON_COMMAND(IDC_NumMultiply, keyMultiply)
      ON_COMMAND(IDC_NumDivide, keyDivide)
      ON_COMMAND(IDC_NumCube, keyCube)
      ON_COMMAND(IDC_NumSquare, keySquare)
      ON_COMMAND(IDC_NumSquareRoot, keySquareRoot)
      ON_COMMAND(IDC_POWER,keyPower)
      ON_COMMAND(IDC_NumMemory, keyMemory)
      ON_COMMAND(IDC_MemoryErase, EraseMemory)
      ON_COMMAND(IDC_NumCE, keyCE)
      ON_COMMAND(IDC_Farenheit, keyFarenheit)
      ON_COMMAND(IDC_Celcius, keyCelcius)
      ON_COMMAND(IDC_Miles, keyMiles)
      ON_COMMAND(IDC_Kilometers, keyKilometers)
      ON_COMMAND(IDC_QUIT, Quit)
      ON_COMMAND(ID_FILE_EXIT,Quit)
      ON_COMMAND(ID_OTHER_HELP,Help)
      ON_COMMAND(ID_OTHER_ABOUT,About)

END_MESSAGE_MAP()
class Calc : public CWinApp
{

public:
Calc() {  }

virtual BOOL InitInstance()
{
        CWinApp::InitInstance();
        Calculator x;
        m_pMainWnd = &x;
        INT_PTR nResponse = x.DoModal();
        return FALSE;
} //close function     

};
//----------------------------------------------------------

Calc SuperFun;
